package com.netty;

import org.junit.Test;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

import static com.netty.util.ByteBufferUtil.debugAll;

public class NioDemo1 {


    //普通io读取文件
    @Test
    public void test01(){

        try {
            FileInputStream fileInputStream = new FileInputStream("data.txt");

            long start = System.currentTimeMillis();

            byte bytes[]=new byte[1024];

            int n=-1;

            while ((n=fileInputStream.read(bytes,0,1024))!=-1){

                String s = new String(bytes,0,n,"utf-8");

                System.out.println(s);
            }
            long end = System.currentTimeMillis();
            System.out.println("普通io共耗时："+(end-start)+"ms");
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    //缓冲流IO读取文件
    @Test
    public void test02(){

        try {
            BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("data.txt"));

            long start = System.currentTimeMillis();

            byte bytes[]=new byte[1024];

            int n=-1;

            while ((n=bufferedInputStream.read(bytes,0,1024))!=-1){

                String s = new String(bytes,0,n,"utf-8");

                System.out.println(s);
            }

            long end = System.currentTimeMillis();
            System.out.println("缓冲流io共耗时："+(end-start)+"ms");
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    //Nio读取文件position <= limit<=capacity
    @Test
    public void test3(){

        try {
            //获取channel,FileInputStream生成的channel只有读的权利
            FileChannel channel = new FileInputStream("data.txt").getChannel();
            ByteBuffer byteBuffer = ByteBuffer.allocate(1024); //开辟一块缓冲区

            long start = System.currentTimeMillis();
            while (true){

                //写入操作
                int read = channel.read(byteBuffer); //如果read=-1，说明缓存“块”没有数据了

                if(read==-1){
                    break;
                }else {

                    byteBuffer.flip();//读写切换，切换为读的操作，实质上就是把limit=position,position=0


//                    while (byteBuffer.hasRemaining()){  // 对缓存块进行取数据,position < limit
//
//                        System.out.println((char) byteBuffer.get());
//                    }

//                    byteBuffer.clear(); //切换为写操作，写入权限

                    String de = StandardCharsets.UTF_8.decode(byteBuffer).toString();
                    System.out.println(de);

                    byteBuffer.clear(); //切换为写

//                    byteBuffer.compact();

                }


            }

            long end = System.currentTimeMillis();
            System.out.println("heap nio共耗时："+(end-start)+"ms");

        } catch (Exception e) {
            e.printStackTrace();
        }


    }


    @Test
    public void test4(){

        ByteBuffer byteBuffer = ByteBuffer.allocate(10);

        byteBuffer.put("helloWorld".getBytes());

        debugAll(byteBuffer);

        byteBuffer.flip(); //读模式

        while (byteBuffer.hasRemaining()){

            System.out.println((char)byteBuffer.get());
        }


        byteBuffer.flip();

        System.out.println(StandardCharsets.UTF_8.decode(byteBuffer).toString());

    }

    //字符串与ByteBuffer的相互转换
    @Test
    public void test5(){


        //字符串转换成ByteBuffer
        ByteBuffer byteBuffer = StandardCharsets.UTF_8.encode("hello world\nabc\n\baaa");
        //通过StandardCharsets的encode方法获得ByteBuffer，此时获得的ByteBuffer为读模式，无需通过flip切换模式
//        byteBuffer.flip(); //这句话不能加，encode转换成ByteBuffer默认是读模式
        while (byteBuffer.hasRemaining()){

            System.out.printf("%c",(char)byteBuffer.get());
        }

        byteBuffer.flip();
        //ByteBuffer转换成String
        String str = StandardCharsets.UTF_8.decode(byteBuffer).toString();
        System.out.println("\n--------------");
        System.out.println(str);
    }

    //粘包和半包
    @Test
    public void test6(){

        String msg = "hello,world\nI'm abc\nHo";

        ByteBuffer byteBuffer = ByteBuffer.allocate(32);

        byteBuffer.put(msg.getBytes());



        byteBuffer=splitGetBuffer(byteBuffer);


        byteBuffer.put("w are you?\n".getBytes()); //多段发送数据


        byteBuffer=splitGetBuffer(byteBuffer);

        byteBuffer.put("aa  bccdd?\n".getBytes()); //多段发送数据

        byteBuffer=splitGetBuffer(byteBuffer);

    }

    private ByteBuffer splitGetBuffer(ByteBuffer byteBuffer) {

        byteBuffer.flip();
        StringBuilder stringBuilder = new StringBuilder();
        int index=-1;
        for (int i = 0; i < byteBuffer.limit(); i++) {

            if(byteBuffer.get(i)!='\n'){ //get(i)不会让position+1

                stringBuilder.append((char) byteBuffer.get(i));


            }else{
                index=i; //记录最后一个分隔符下标
                String data = stringBuilder.toString();
                ByteBuffer dataBuf = ByteBuffer.allocate(data.length());
                dataBuf.put(data.getBytes());
                dataBuf.flip();
                debugAll(dataBuf);
                dataBuf.clear();
                stringBuilder=new StringBuilder();
            }
        }

        ++index;
        ByteBuffer temp = ByteBuffer.allocate(byteBuffer.capacity());
        for (;index<byteBuffer.limit();++index){

            temp.put(byteBuffer.get(index));
        }

        return temp;
    }


}
